-- LeiTingAgent
-- Created by chengb Sep/21/2016
-- 雷霆平台代理

module("LeiTingAgent", package.seeall);

update("game/sdk/LeiTingDataReport")

-- 雷霆安卓渠道编码
local LEITING_CHANNAL_TABLE = {
    ["110001"] = "leiting",    -- 雷霆官网
    ["110002"] = "ltqihoo",    -- 360手助
    ["110003"] = "ltuc",       -- UC
    ["110004"] = "ltdl",       -- 当乐网
    ["110005"] = "ltbaidu",    -- 百度游戏
    ["110006"] = "ltxiaomi",   -- 小米游戏
    ["110007"] = "ltarz",      -- 艾瑞泽
    ["110008"] = "ltxmy",      -- 新马运
    ["120001"] = "ltmsdk",     -- 应用宝
    ["120002"] = "ltwandou",   -- 豌豆荚
    ["120003"] = "ltanzhi",    -- 安智市场
    ["120004"] = "ltappchina", -- 应用汇
    ["120005"] = "ltwandoutwo",-- 豌豆荚2
    ["130001"] = "ltlenovo",   -- 联想巨好玩
    ["130002"] = "ltoppo",     -- OPPO
    ["130003"] = "ltjinli",    -- 金立游戏大厅
    ["130004"] = "lt37",       -- 37游戏(魅族)
    ["130005"] = "lthuawei",   -- 华为
    ["130007"] = "ltcoolpad",  -- 酷派
    ["130008"] = "ltvivo",     -- VIVO
    ["130009"] = "lt4399",     -- 4399
    ["130010"] = "ltmzw",      -- 拇指玩
    ["130011"] = "ltmz",       -- 魅族
    ["130012"] = "ltyl",       -- 游龙
    ["130013"] = "ltydmg",     -- 移动咪咕
    ["130014"] = "ltlb",       -- 猎宝
    ["130015"] = "ltyk",       -- 优酷
    ["130016"] = "ltgp",       -- 果盘（叉叉助手）
    ["130017"] = "lttoutiao",  -- 今日头条
    ["130018"] = "ltkugou",    -- 酷狗
    ["130019"] = "ltyiwan",    -- 益玩
    ["130020"] = "ltyiyou",    -- 谊游（TT语音）
    ["130021"] = "ltkaopu",    -- 靠谱助手
    ["130022"] = "ltyijie",    -- 易接
    ["130023"] = "ltly",       -- 麟游
    ["130024"] = "ltdy",       -- 斗鱼
    ["130025"] = "ltyy",       -- yy
    ["130026"] = "ltmg",       -- 芒果
    ["130044"] = "ltiapppay",  -- 爱贝
    ["130045"] = "ltxw",       -- 小沃
    ["130047"] = "ltydmm",     -- 移动MM
}

-- 雷霆官方渠道
local LEITING_CHANNEL_NO = "110001";

-- 雷霆中心的账号信息
local userInfo = {};

-- 内部函数声明
local onFetchProductsInfo;
local onLeitingLoginCallBack;
local onLeiTingLogoutCallback;
local onLeiTingQuitCallback;
local onLeiTingPayCallback;
local onPrechargeFail;
local processLoginSuccess;
local whenUserLevelUp;
local whenLoginOk;
local whenCreateNewChar;
local whenPreLoadMainOk;

function init()
    -- 注册登录回调
    SdkMgr.registerJavaCallback("onLeitingLoginCallBack", onLeitingLoginCallBack);

    -- 注册登出回调
    SdkMgr.registerJavaCallback("onLeiTingLogoutCallback", onLeiTingLogoutCallback);

    -- 注册退出回调
    SdkMgr.registerJavaCallback("onLeiTingQuitCallback", onLeiTingQuitCallback);

    -- 注册充值回调
    SdkMgr.registerJavaCallback("onLeiTingPayCallback", onLeiTingPayCallback);

    EventMgr.removeAll("LeiTingAgent");

    -- 关注玩家升级的回调
    EventMgr.register("LeiTingAgent", event.USER_LEVEL_UP, whenUserLevelUp);

    -- 关注玩家登录的回调
    EventMgr.register("LeiTingAgent", event.LOGIN_OK, whenLoginOk);

    -- 关注创建角色的事件
    EventMgr.register("LeiTingAgent", event.CREATE_NEW_CHAR, whenCreateNewChar);

    -- 关注预加载主场景完毕的事件
    EventMgr.register("LeiTingAgent", event.PRELOAD_MAIN_OK, whenPreLoadMainOk);
end

-- 预加载主场景完毕
function whenPreLoadMainOk()
    -- 检测激活上报
    LeiTingDataReport.checkActiveReport();
end

-- 登录
function login()
    callJavaFuncWithClass("com.ChannelDelegate", "login", {}, "()V");
end

-- 登出
function logout()
    callJavaFuncWithClass("com.ChannelDelegate", "logout", {}, "()V");
end

----------------------
-- 购买商品
-- @param sku 商品库存标识
function buyPurchase(sku)
    function onPrechargeOk(orderId)
        -- 获取商品的价格
        local price = PurchaseToolkit.getProductPrice(sku);
        if price == 0 then
            -- 获取到的价格为零，说明之前拉取商品列表时失败了
            EventMgr.fire(event.RECHARGE_FAIL);
            return;
        end

        local item = PurchaseToolkit.findPurchase(sku);
        if not item then
            assert(false, string.format("商品(%s)不存在！", sku));
            return;
        end

        local params = {
            userId        = userInfo["userId"],
            userKey       = userInfo["userKey"];
            zoneId        = tostring(getCurrentServerId()), -- 区组Id
            money         = tostring(price * 100),          -- 商品价格，以分为单位
            type          = userInfo["type"],
            notifyUri     = LEITING_PAY_NOTIFY_URL,         -- 支付通知地址
            userName      = userInfo["userName"];
            roleId        = ME.user:getRid(),
            roleName      = ME.user:getName(),
            productName   = item["name"];
            productNumber = item["amount"];
            productId     = sku,
            orderId       = orderId,
            showGameArea  = "0",                            -- 是否显示游戏区组：1 显示  0 不显示
        };

        -- 发起支付
        local jsonStr = json.encode(params);
        callJavaFuncWithClass("com.ChannelDelegate", "pay", {jsonStr}, "(Ljava/lang/String;)V");
    end

    local platform   = PUBLISH_TYPE_LT;
    local payChannel = getLastAccountChannel();

    -- 先进行预充值，预充值成功后得到预充值订单号，再通过SDK进行正式充值
    PurchaseToolkit.prePurchase(sku, LEITING_PURCHASE_PRE_URL, platform, payChannel,
        onPrechargeOk, onPrechargeFail);
end

-- 预充值失败
function onPrechargeFail()
    trace("LeiTingAgent", "precharge failed");

    -- 充值失败
    EventMgr.fire(event.RECHARGE_FAIL);
end

-- 创建角色的回调
function whenCreateNewChar(args)
    local charName   = args.charName;
    local roleId     = args.rid;
    local serverId   = getCurrentServerId();
    local serverName = getCurrentServerName();
    local level      = 1;

    local params = {
        roleId    = roleId,     -- 角色ID
        roleName  = charName,   -- 角色名称
        roleLevel = level,      -- 角色等级
        zoneId    = serverId,   -- 区服ID
        zoneName  = serverName, -- 区服名称
    };

    local jsonStr = json.encode(params);

    callJavaFuncWithClass("com.ChannelDelegate", "createRoleReport", {jsonStr}, "(Ljava/lang/String;)V");
end

-- 玩家登录的回调
function whenLoginOk()
    -- 下载商品列表
    PurchaseToolkit.fetchProductsInfo(LEITING_PURCHASE_INFO_FILE_URL, onFetchProductsInfo);

    local rid  = ME.user:getRid();
    local name = ME.user:getName();
    local level      = ME.user:getLevel();
    local serverId   = getCurrentServerId();
    local serverName = getCurrentServerName();
    local roleCTime  = ME.user:getRoleCreateTime();

    local args = {
        action    = 1,          -- 1为登录动作，2为创建角色
        roleId    = rid,        -- 角色ID
        roleName  = name,       -- 角色名称
        roleLevel = level,      -- 角色等级
        zoneId    = serverId,   -- 区服ID
        zoneName  = serverName, -- 区服名称
        roleCTime = roleCTime,  -- 角色创建时间
    };

    local jsonStr = json.encode(args);

    callJavaFuncWithClass("com.ChannelDelegate", "loginReport", {jsonStr}, "(Ljava/lang/String;)V");
end

-- 玩家升级的回调
function whenUserLevelUp(args)
    local level = args.level;
    local rid = ME.user:getRid();
    local name = ME.user:getName();
    local serverId = getCurrentServerId();
    local serverName = getCurrentServerName();
    local roleLevelMTime = TimeM.getServerTime();
    local roleCTime = ME.user:getRoleCreateTime();

    local params = {
        roleId    = rid,                 -- 角色ID
        roleName  = name,                -- 角色名称
        roleLevel = level,               -- 角色等级
        zoneId    = serverId,            -- 区服ID
        zoneName  = serverName,          -- 区服名称
        roleCTime = roleCTime,           -- 角色创建时间
        roleLevelMTime = roleLevelMTime, -- 等级变化时间(选传)
    };

    local jsonStr = json.encode(params);

    -- 升级上报
    callJavaFuncWithClass("com.ChannelDelegate", "levelUpReport", {jsonStr}, "(Ljava/lang/String;)V");
end

-- 根据渠道编码获取渠道标识
function getChannel(channelNo)
    return LEITING_CHANNAL_TABLE[channelNo];
end

-- 雷霆账号登录回调
function onLeitingLoginCallBack(jsonParams)
    trace("LeiTingAgent", "onLeitingLoginCallBack: jsonParams = " .. jsonParams);
    local params = string.parseJsonToTable(jsonParams);
    local status = params.status;
    if status == "1" then
        -- 登录成功
        userInfo = params;
        processLoginSuccess(params);
    elseif status == "9" then
        -- 需要激活
        activateAccount();

        -- 清除上次登录的渠道记录，并将角色踢回登录界面
        setLastAccountChannel("");
        EventMgr.fire(event.THIRD_ACCOUNT_LOGOUT);
    else
        trace("LeiTingAgent", "Leiting account verify fail.");
    end
end

-- 雷霆账号登出的回调
function onLeiTingLogoutCallback(jsonParams)
    trace("LeiTingAgent", "onLeiTingLogoutCallback: jsonParams = " .. jsonParams);
    local params = string.parseJsonToTable(jsonParams);
    local status = params.status;
    if status == "1" then
        -- 注销账号成功
        -- 清除上次登录的渠道记录
        setLastAccountChannel("");
        EventMgr.fire(event.THIRD_ACCOUNT_LOGOUT);
    end
end

-- 雷霆退出游戏的回调
function onLeiTingQuitCallback(jsonParams)
    trace("LeiTingAgent", "onLeiTingQuitCallback: jsonParams = " .. jsonParams);
    local params = string.parseJsonToTable(jsonParams);
    local status = params.status;

    local channelNo = getChannelNo();

    -- 1-退出游戏（兼容老版本）；
    -- 2-退出失败；
    -- 3-拉起游戏自己的退出界面；
    -- 4-直接退出游戏（不需要弹框）
    if status == "3" then
        -- 直接退出游戏
        simpleExitSystem();
    elseif channelNo ~= LEITING_CHANNEL_NO and status == "1" then
        -- 非官方渠道
        simpleExitSystem();
    end
end

-- 雷霆充值的回调
function onLeiTingPayCallback(jsonParams)
    trace("LeiTingAgent", "onLeiTingPayCallback: jsonParams = " .. jsonParams);
    local params = string.parseJsonToTable(jsonParams);
    local status = params.status;

    if status == "1" then
        -- 充值成功
        ChargeM.rechargeHandle(sku);
    else
        -- 充值失败
        EventMgr.fire(event.RECHARGE_FAIL);
    end
end

-- 雷霆账号登录成功的处理
function processLoginSuccess(params)
    local userId    = params.userId;
    local game      = params.game;
    local channelNo = params.channelNo;
    local token     = params.token;

    assert(type(userId)    == "string");
    assert(type(game)      == "string");
    assert(type(channelNo) == "string");
    assert(type(token)     == "string");

    -- 根据渠道编码获取渠道标识
    local channel = getChannel(channelNo);
    if not channel then
        assert(false, "未知的渠道：%s", tostring(channelNo));
        return;
    end

    -- 设置账号信息
    -- extra_raw中存放的是雷霆平台返回的最原始的认证信息，aaa拿到这份信息后还要重新认证
    local info = {
        ["account"] = userId,
        ["extra"] = {
            ["3rdplatform"] = channel,
            ["channelNo"]   = channelNo,
        },
        ["extra_raw"] = {
            ["3rdplatform"] = CHANNEL_LT,
            ["channel"]     = channel,
            ["channelNo"]   = channelNo,
            ["game"]        = game,
            ["userId"]      = userId,
            ["token"]       = token,
        },
    };
    set3rdAccountLoginInfo(channel, info);

    -- 抛出第三方账号登录事件
    EventMgr.fire(event.THIRD_ACCOUNT_LOGINED, {
        ["channel"] = channel,
        ["loginInfo"] = info,
        ["channel_raw"] = CHANNEL_LT,
    });
end

-- 获取渠道编码
function getChannelNo()
    if isAndroidPlatform() then
        return callJavaFuncWithClass("com.ChannelDelegate", "getChannelType", {}, "()Ljava/lang/String;");
    end
    return "";
end

-- 是否弹出游戏退出框
function isConfirmExit()
    return callJavaFuncWithClass("com.ChannelDelegate", "isConfirmExit", {}, "()Z");
end

-- 显示个人中心
function showAccountCenter()
    return callJavaFuncWithClass("com.ChannelDelegate", "showAccountCenter", {}, "()V");
end

-- 显示客服专区
function showHelper()
    local args = {
        roleName  = ME.user:getName(),                  -- 角色名称
        roleLevel = ME.user:getLevel(),                 -- 角色等级
        gameZone  = tostring(getCurrentServerId()),     -- 区服ID
    };

    local jsonStr = json.encode(args);

    return callJavaFuncWithClass("com.ChannelDelegate", "showHelper", {jsonStr}, "(Ljava/lang/String;)V");
end

-- 切换游戏账号
function switchAccount()
    return callJavaFuncWithClass("com.ChannelDelegate", "switchAccount", {}, "()V");
end

-- 激活账号
function activateAccount()
    callJavaFuncWithClass("com.ChannelDelegate", "activateAccount", {}, "()V");
end

-- 拉取商品列表信息成功回调
function onFetchProductsInfo(productsInfo)
    for sku, productInfo in pairs(productsInfo) do
        local price = productInfo["price"] .. getLocStr("yuan");
        MarketM.recordSkuPrice(sku, price);
    end
end

-- 获取媒体分包编码
function getMedia()
    if isAndroidPlatform() then
        return callJavaFuncWithClass("com.ChannelDelegate", "getMedia", {}, "()Ljava/lang/String;");
    end
    return "";
end

-- 生成手机验证码cookie
function generateMobileCookie()
    local sid = userInfo["userId"];  -- 玩家id
    local phoneCodeKey = "leiting";  -- 秘钥
    return callJavaFuncWithClass("com.ChannelDelegate", "encryptMobileCookie",
        { sid, phoneCodeKey, }, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
end

-- 查询是否绑定手机
-- callback : 查询成功后的回调，如果已绑定，则在回调中返回手机号，否则返回nil
function getBindedPhone(callback)
    local sid = userInfo["userId"];         -- 雷霆玩家id
    local cookie = generateMobileCookie();  -- cookie
    local userName = userInfo["userName"];  -- 雷霆玩家名称

    local params = string.format("sid=%s&cookie=%s&username=%s", sid, cookie, userName);

    trace("LeiTingAgent", "getBindedPhone params = " .. params);

    local function myCallback(response)
        trace("LeiTingAgent", "getBindedPhone response = %o", response);

        if callback then
            result = string.parseJsonToTable(response);
            if result["status"] == "1" then
                callback(result["bindPhone"]);
            else
                callback();
            end
        end
    end
    postDataToRemoteHost(LEITING_PHONE_BIND_QUERY_URL, params, myCallback);
end